<template>

  <!--  <div>-->
  <!-- 图标式刷新按钮 -->
  <div class="container"
       style="white-space: nowrap; height: 100%; display: flex; justify-content: space-between; align-items: center;">
    <!-- 左侧内容 -->
    <div style="display: flex; align-items: center;">
      <h3 style="margin-right: 10px; line-height: 40px; margin-bottom: 0; margin-left: 5px;">客户端</h3>
      <button class="btn text-white"
              style="background-color: #ffffff; width: 40px; height: 40px; border: none; border-radius: 8px; display: flex; justify-content: center; align-items: center; padding: 0; margin: 0;"
              @click="update_client_status();update_manage_datasets();"> <!-- 绑定点击事件 -->
        <i class="fas fa-sync" style="font-size: 23px; color: #aba8a8;"></i>
      </button>
    </div>
    <!-- 右侧内容 -->
    <div style="display: flex; align-items: center; margin-right: 10px;">
      <button class="page-btn" :class="{ active: page_status  === 'client' }" @click="setPageStatus('client')">客户端
      </button>
      <button class="page-btn" :class="{ active: page_status  === 'data_manage' }"
              @click="setPageStatus('data_manage')">数据管理
      </button>
    </div>
  </div>

  <div v-if="page_status ==='client'">

    <div class="container"
         style="white-space: nowrap; height: 100%; display: flex; justify-content: center; align-items: center;">
      <div class="card text-center p-3 m-0"
           style="display: flex; align-items: center; justify-content: space-between; width: 100%;">
        <div style="display: flex; align-items: center; justify-content: flex-start;">
          <div class="row mt-2 mb-2">
            <div class="col">
              <h3 class="mb-3 mt-3" style="margin-right: 50px;" v-for="(user, index) in Localuser" :key="index">
                用户名: {{ user.name }}
              </h3>
            </div>
            <!--          <div class="col">-->
            <!--            <button class="mb-3 mt-3 btn bg-primary-heavy text-white"-->
            <!--                    style="white-space: nowrap;" @click="update_client_status">-->
            <!--              刷新-->
            <!--            </button>-->
            <!--          </div>-->
          </div>
        </div>
      </div>
    </div>
    <!--  <div :class="{ 'locked': isLocked }">-->
    <div>
      <!--  <div class="container mt-4" v-if="!isLocked">-->
      <!--    <div class="card text-center">-->
      <!--      <div class="card-body">-->
      <!--        <input type="file" id="fileInput" @change="handleFileChange" />-->
      <!--        <input type="file" id="folderInput" webkitdirectory multiple />-->
      <!--        <button class="btn bg-primary-heavy text-white" @click="uploadFiles">上传数据集</button>-->
      <!--        <button class="btn bg-primary-heavy text-white" style="white-space: nowrap;  position: fixed; right: 15%; " @click="update_client_status">刷新</button>-->
      <!--      </div>-->
      <!--    </div>-->
      <!--  </div>-->

      <div class="container" style="white-space: nowrap; height: 100%;">
        <div class="card text-center">
          <div class="card-body">
            <h5 class="card-title">用户信息</h5>
            <div class="table-responsive">
              <table class="table">
                <thead>
                <tr>
                  <th scope="col">客户端设置</th>
                  <th scope="col">数据集设置</th>
                  <th scope="col">模型状态</th>
                  <th scope="col">验证结果</th>
                  <th scope="col">追踪</th>
                  <th scope="col">追踪结果</th>
                </tr>
                </thead>
                <tbody>
                <tr v-for="(user, index) in Localuser" :key="index">
                  <td>
                    <select v-model="user.setting" class="form-select">
                      <option v-for="(option, optionIndex) in settingOptions" :key="optionIndex">{{ option }}</option>
                    </select>
                  </td>
                  <td>
                    <select v-model="user.dataset" class="form-select dropdown-scroll">
                      <option disabled value="">请选择数据集</option>
                      <option v-for="(option, optionIndex) in settingData" :key="optionIndex" :value="option">
                        {{ option }}
                      </option>
                    </select>
                  </td>
                  <td>{{ user.status }}</td>
                  <td>{{ user.result1 }}</td>
                  <td>
                    <button class="btn bg-primary-heavy text-white" @click="startProcess(user, index)"
                            :disabled="isLocked||buttons_status[5]">请求追踪
                    </button>
                  </td>
                  <td v-html="formatResult(user.result2)"></td>
                </tr>
                </tbody>
              </table>
            </div>
          </div>
        </div>
      </div>

      <div class="container mt-0" style="white-space: nowrap; height: 100%;">
        <div class="card mt-4 text-center">
          <div class="card-body">
            <div class="row mt-2 mb-2">
              <div class="col">
                <button class="btn bg-primary-heavy text-white btn-lg" style="width: 100%; height: 100%"
                        @click="handleButtonClick(6)" :disabled="isLocked||buttons_status[0]">参与学习
                </button>
              </div>
              <div class="col">
                <button class="btn bg-primary-heavy text-white btn-lg" style="width: 100%; height: 100%"
                        @click="showInitConfirmation" :disabled="isLocked||buttons_status[1]">初始化
                </button>
              </div>
              <div class="col">
                <button class="btn bg-primary-heavy text-white btn-lg" style="width: 100%; height: 100%"
                        @click="handleButtonClick(2)" :disabled="isLocked||buttons_status[2]">开始训练
                </button>
              </div>
              <div class="col">
                <button class="btn bg-primary-heavy text-white btn-lg" style="width: 100%; height: 100%"
                        @click="handleButtonClick(3)" :disabled="isLocked||buttons_status[3]">上传模型
                </button>
              </div>
              <div class="col">
                <button class="btn bg-primary-heavy text-white btn-lg " style="width: 100%; height: 100%"
                        @click="handleButtonClick(5)" :disabled="isLocked||buttons_status[4]">验证模型
                </button>
              </div>
            </div>
          </div>
        </div>
      </div>

      <div class="container mt-4" style="white-space: nowrap; height: 100%;">
        <div class="card mt-0 text-center">
          <div class="card-body">
            <div class="row mt-0 mb-2 me-4">
              <button class="btn bg-primary-heavy text-white" @click="downloadFile" :disabled="isLocked">导出模型文件
              </button>
            </div>
            <div class="row mt-0 mb-2 me-4">
              <button class="btn bg-primary-heavy text-white" @click="downloadFile1">
                下载demo.py和model.pth的使用说明
              </button>
            </div>
            <!--          <div class="row mt-0 mb-2 me-4">-->
            <!--            <button class="btn bg-primary-heavy text-white" @click="showLogoutConfirmation"-->
            <!--                    :disabled="isLocked||buttons_status[6]">-->
            <!--              注销客户端-->
            <!--            </button>-->
            <!--          </div>-->
          </div>
          <div class="mt-2 ms-6">
            <p>注：导出的模型文件model.pth可以通过相应的模型代码直接加载并使用</p>
            <p>具体使用方法可以查看model.pth使用说明</p>
          </div>
        </div>
      </div>

      <!-- 注销弹窗 -->
      <!--    <div v-if="isLogoutConfirmationVisible" class="modal">-->
      <!--      <div class="modal-content">-->
      <!--        <h4>确认注销</h4>-->
      <!--        <p>您确定要注销客户端吗？</p>-->
      <!--        <button class="btn bg-primary-heavy  text-white" @click="logout">确认</button>-->
      <!--        <button class="btn btn-secondary" @click="cancelLogout">取消</button>-->
      <!--      </div>-->
      <!--    </div>-->

    </div>
  </div>

  <!-- 数据集管理 -->
  <div v-if="page_status === 'data_manage'">
    <div class="container" style="white-space: nowrap; height: 100%; padding: 20px;">
      <!-- 顶部按钮 -->
      <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
        <h4>数据集列表</h4>
        <button class="btn-add" @click="showCreateDatasetModal">+ 新增数据集</button>
      </div>

      <!-- 列表 -->
      <table class="data-table">
        <thead>
        <tr>
          <th>数据集名称</th>
          <th>上传时间</th>
          <th>操作</th>
        </tr>
        </thead>
        <tbody>
        <tr
            v-for="(dataset, index) in paginatedData"
            :key="index"
            :class="{ 'row-odd': index % 2 === 0, 'row-even': index % 2 !== 0 }"
        >
          <td>{{ dataset.dataset_name }}</td>
          <td>{{ dataset.upload_time }}</td>
          <td>
            <button class="btn-action" @click="showDeleteConfirmation(dataset)"
                    :disabled="dataset.isdefault||buttons_status[7]">删除
            </button>
          </td>
        </tr>
        </tbody>
      </table>

      <!-- 分页 -->
      <div class="pagination-container">
        <!-- 分页信息 -->
        <div class="pagination-info">
          共 {{ manage_datasets.length }} 条数据，每页 {{ itemsPerPage }} 条，共 {{ totalPages }} 页
        </div>
        <!-- 分页操作 -->
        <div class="pagination">
          <button :disabled="currentPage === 1" @click="prevPage">上一页</button>
          <span
              v-for="page in visiblePages"
              :key="page"
              :class="{ active: currentPage === page }"
              @click="jumpToPage(page)"
          >
            {{ page === '...' ? '...' : page }}
          </span>
          <button :disabled="currentPage === totalPages" @click="nextPage">下一页</button>
          <!-- 页码输入框 -->
          <div class="jump-to">
            跳至
            <input type="number" v-model="inputPage" @keydown.enter="goToPage"/>
            页
          </div>
        </div>
      </div>
    </div>
  </div>

  <!-- 模态窗口 (动效窗口) -->
  <div v-if="isModalVisible" class="modal-overlay">
    <div class="modal-content">
      <div class="spinner"></div>
      <h5 class="text-center  mt-3">处理中，请稍候...</h5>
    </div>
  </div>

  <!-- 初始化弹窗 -->
  <div v-if="isInitConfirmationVisible" class="modal">
    <div class="modal-content">
      <h4>初始化</h4>
      <p>您确定要执行初始化操作吗？</p>
      <button class="btn bg-primary-heavy  text-white" @click=handleButtonClick(1)>确认</button>
      <button class="btn btn-secondary" @click="cancelInit">取消</button>
    </div>
  </div>
  <!-- 新增数据集弹窗 -->
  <!--  <div v-if="isInitConfirmationVisible" class="modal">-->
  <!--    <div class="modal-content">-->
  <!--      <h4>初始化</h4>-->
  <!--      <p>您确定要执行初始化操作吗？</p>-->
  <!--      <button class="btn bg-primary-heavy  text-white" @click=handleButtonClick(1)>确认</button>-->
  <!--      <button class="btn btn-secondary" @click="cancelInit">取消</button>-->
  <!--    </div>-->
  <!--  </div>-->
  <!-- 删除数据集弹窗 -->
  <div v-if="isDeleteConfirmationVisible" class="delete-modal">
    <div class="delete-modal-content">
      <h4 class="delete-modal-title">提示</h4>
      <p class="delete-modal-message">数据集删除后不可恢复，是否继续？</p>
      <div class="delete-modal-buttons">
        <button class="btn delete-cancel-btn" @click="cancelDelete">取消</button>
        <button class="btn delete-confirm-btn" @click="confirmDelete">确定</button>
      </div>
    </div>
  </div>
  <!-- 新建数据集弹窗 -->
  <div v-if="isCreateDatasetVisible" class="create-modal">
    <div class="create-modal-content">
      <h4 class="create-modal-title">新增数据集</h4>
      <div class="add-row">
        <div class="upload-row">
          <label class="upload-label">上传数据：</label>
          <!-- 添加 ref 来引用文件输入框 -->
          <input type="file" @change="handleFileChange" accept=".npz" class="file-input" ref="fileInput"/>
          <!--        <span class="file-info">当前仅支持 .npz 格式文件，大小不超过 10 MB</span>-->
        </div>
        <div class="upload-row">
          <span class="file-info">注：当前仅支持 .npz 格式文件，大小不超过 10 MB</span>
        </div>
      </div>

      <!--       <div v-if="errorMessage" class="error-message">{{ errorMessage }}</div>-->
      <div class="create-modal-buttons">
        <button class="btn create-cancel-btn" @click="cancelCreate">取消</button>
        <button class="btn create-confirm-btn" @click="confirmCreate" :disabled="!selectedFile || uploading">确定
        </button>
      </div>
    </div>
  </div>
  <CustomAlert ref="customAlert"/>
</template>

<script setup>
import {onMounted, onUnmounted, ref, computed} from 'vue';
import {useStore} from "vuex";
import axios from 'axios';
// import { io } from 'socket.io-client';
// import Swal from 'sweetalert2';
import CustomAlert from './CustomAlert.vue';

const initialUser = [
  {
    name: 'user1',
    setting: '默认设置',
    dataset: '数据集一',
    status: '未训练',
    result1: '未验证',
    result2: 'a55f66d4-a2fd-453e-96d0-984f7e5ef788,3974a7cf-4af8-427a-b51d-2dc320eab6f4,12ac1de4-f117-4c8b-87d6-cc5a5623d754\n',
    client_id: '1'
  },
];
const initialDataset = ['数据集一', '数据集二', '数据集三']
const initialManageDatasets = [
  {
    dataset_name: '数据集1',
    upload_time: '2024-11-1 11:00',
    isdefault: true,
  },
]
const Localuser = ref([]);
const settingOptions = ['默认设置', '伪造hash', '伪造签名1', '伪造签名2'];
const settingData = ref([]); // 使用 ref 来保证 reactivity
const manage_datasets = ref([]);
const userInfo_clientId = ref();
const userInfo_userId = ref();
const userInfo_username = ref();
const buttons_status = ref([false, true, true, true, true, true, true, false]);

const loadUsersFromSessionStorage = () => {
  // 校验并加载数据集
  try {
    const storedDatasetString = sessionStorage.getItem('local_dataset');
    if (storedDatasetString) {
      const storedDataset = JSON.parse(storedDatasetString);
      if (Array.isArray(storedDataset)) {
        settingData.value = storedDataset;
      } else {
        console.error('Loaded dataset is not an array:', storedDataset);
        settingData.value = [...initialDataset];
      }
    } else {
      console.warn('No dataset found in sessionStorage, using initial dataset');
      settingData.value = [...initialDataset];
    }
  } catch (error) {
    console.error('Error loading dataset from sessionStorage:', error);
    settingData.value = [...initialDataset];
  }

  // 校验并加载用户信息
  try {
    const storedUserString = sessionStorage.getItem('local_user');
    if (storedUserString) {
      const storedUser = JSON.parse(storedUserString);
      if (Array.isArray(storedUser)) {
        Localuser.value = storedUser;
      } else {
        console.error('Loaded user is not an array:', storedUser);
        Localuser.value = [...initialUser];
      }
    } else {
      console.warn('No user found in sessionStorage, using initial user');
      Localuser.value = [...initialUser];
    }
  } catch (error) {
    console.error('Error loading user from sessionStorage:', error);
    Localuser.value = [...initialUser];
  }
  // 校验并加载数据集管理信息
  try {
    const storedManageDatasets = sessionStorage.getItem('datasets_manage');
    if (storedManageDatasets) {
      const storedDatasets = JSON.parse(storedManageDatasets);
      if (Array.isArray(storedDatasets)) {
        manage_datasets.value = storedDatasets;
      } else {
        console.error('Loaded manage_datasets is not an array:', storedDatasets);
        manage_datasets.value = [...initialManageDatasets];
      }
    } else {
      console.warn('No user found in sessionStorage, using initial manage_datasets');
      manage_datasets.value = [...initialManageDatasets];
    }
  } catch (error) {
    console.error('Error loading manage_datasets from sessionStorage:', error);
    manage_datasets.value = [...initialManageDatasets];
  }
};

const saveUsersToSessionStorage = () => {
  try {
    sessionStorage.setItem('local_user', JSON.stringify(Localuser.value));
    sessionStorage.setItem('local_dataset', JSON.stringify(settingData.value));
    sessionStorage.setItem('datasets_manage', JSON.stringify(manage_datasets.value));
  } catch (error) {
    console.error('Error saving users to sessionStorage:', error);
  }
};

// 设置axios
const apiBaseUrl = (window.webConfig && window.webConfig.ClientBaseUrl);
const apiClient = axios.create({
  baseURL: apiBaseUrl, // 基础URL
});

// WebSocket setup
// let socket;
// const isConnecting = ref(false);  // 标志连接状态

// const connectWebSocket = () => {
//   if (socket) {
//     console.warn('WebSocket is already connected or connecting');
//     return;  // 如果已经连接或正在连接，直接返回
//   }
//
//   isConnecting.value = true;  // 设置连接状态
//   socket = io(apiBaseUrl); // 请确保这个 URL 与后端 WebSocket 服务器一致
//
//   socket.on('connect', () => {
//     console.log('WebSocket connected');
//     isConnecting.value = false;  // 重置连接状态
//   });
//
//   socket.on('local_train', () => {
//     // 统计所有用户的setting值，并向后端发送请求
//     Localuser.value.forEach(user => {
//       user.status = '训练完成';
//     });
//     train_condition.value = false;
//     isButtonClicked.value = false;
//     isModalVisible.value = false;
//     saveUsersToSessionStorage();
//     alert("客户端训练完成");
//   });
//
//   socket.on('update', (data) => {
//     if (data && typeof data.status === 'boolean') {
//       Localuser.value.forEach(user => {
//         user.status = '已接收';
//       });
//       saveUsersToSessionStorage();
//     } else {
//       console.warn('收到的消息格式不正确:', data);
//     }
//     alert("聚合结果已接收");
//   });
//
//   socket.on('return_result', (data) => {
//     Localuser.value.forEach(user => {
//       user.result2 = data.unhonest_participant.join(",");
//     });
//     saveUsersToSessionStorage();
//     alert("追踪结果已返回");
//   });
//
//   socket.on('agg_verify', () => {
//     alert("聚合服务器验证未通过，请重新训练模型");
//   });
//
//   socket.on('disconnect', () => {
//     console.log('WebSocket disconnected, reconnecting...');
//     isConnecting.value = false;  // 重置连接状态
//     setTimeout(connectWebSocket, 1000);  // 1秒后重连
//   });
// };

// 页面切换
const page_status = ref('client'); // 当前页面状态
// 更新页面状态为上一页或下一页
const setPageStatus = (status) => {
  page_status.value = status;
  console.log(`当前页面状态: ${status}`);
};

// 设置值转换函数
const convertSettingToNumber = (setting) => {
  switch (setting) {
    case '默认设置':
      return 0;
    case '伪造hash':
      return 1;
    case '伪造签名1':
      return 2;
    case '伪造签名2':
      return 3;
    default:
      return -1; // 或其他合适的默认值
  }
};

//限制按钮在未响应前点击
const isProcessing = ref(false);
const startProcess = async (user) => {
  if (isProcessing.value) {
    // alert('请求正在处理中...');
    await customAlert.value.open("请求正在处理中...");
    return;
  }
  isProcessing.value = true;
  user.result2 = '处理中...';
  await customAlert.value.open("客户端请求追踪恶意参与方...");
  // alert("客户端请求追踪恶意参与方...");
  try {
    const response = await apiClient.get('/client_status');
    if (response.status === 200) {
      console.log(response.data)
      const trace_state = response.data.trace_step_status;
      console.log("trace_step_status:", response.data);
      if (trace_state === "step_none") {
        await customAlert.value.open("已全局重置，请重新参与学习");
        console.log(response.data);
        console.log(response.data.user.name);
        console.log(userInfo_userId.value);
        // 从后端获取并更新 Localuser 信息
        Localuser.value.forEach(user => {
          user.name = response.data.user.name;
          user.setting = response.data.user.setting;
          user.dataset = response.data.user.dataset;
          user.status = response.data.user.status;
          user.result1 = response.data.user.result1;
          user.result2 = response.data.user.result2;
          user.client_id = response.data.user.client_id;
        });
        // 设置按钮状态
        set_buttons(response.data.user.step_status);
        if (response.data.user.step_status !== "step_none") {
          // 判断 user.name 与 userInfo.userid 是否相等
          isLocked.value = (response.data.user.name !== userInfo_username.value);
        }
        if (response.data.user.step_status === "step_none") {
          settingData.value = [...initialDataset];
        }
      } else {
        // const response = await axios.post(`${process.env.VUE_APP_BACKEND_API}/Client.vue`, {
        const response = await apiClient.post(`/request_trace`);

        if (response.status === 200) {
          update_client_status();
          console.log('已请求追踪', response.data);
        }
      }
    }
  } catch (error) {
    console.error('请求失败:', error);
  } finally {
    isProcessing.value = false;
  }
};

// 上传数据集
// const uploadFiles = async () => {
//   const fileInput = document.getElementById('fileInput');
//   const folderInput = document.getElementById('folderInput');
//
//   // 获取所选文件
//   const files = [...fileInput.files, ...folderInput.files];
//
//   if (files.length === 0) {
//     alert('请至少选择一个文件或文件夹');
//     return;
//   }
//
//   const formData = new FormData();
//   for (const file of files) {
//     formData.append('files[]', file);
//   }
//
//   try {
//     const response = await apiClient.post('/upload_files', formData, {
//       headers: {
//         'Content-Type': 'multipart/form-data',
//       },
//     });
//
//     if (response.status === 200) {
//     alert('文件上传成功'); // 这里需要确保响应状态为200
//       console.log('上传响应:', response.data);
//   } else {
//     alert('文件上传失败');
//   }
//
//   } catch (error) {
//     console.error('文件上传失败:', error);
//     alert('文件上传失败');
//   }
// };

//用于初始化
const isInitConfirmationVisible = ref(false);
const showInitConfirmation = () => {
  isInitConfirmationVisible.value = true;
};
const cancelInit = () => {
  isInitConfirmationVisible.value = false;
};
const isModalVisible = ref(false);  // 控制模态窗口显示状态
// 限制按钮在未响应前点击
const isButtonClicked = ref(false);
// 设置客户端动效状态
// const train_condition = ref(false);

const customAlert = ref(null);
const handleButtonClick = async (buttonId) => {
  try {
    // 检查按钮是否已经被点击，如果是，则直接返回
    if (isButtonClicked.value) {
      // alert('正在等待上一次请求的响应，请稍后...');
      // showAlert('正在等待上一次请求的响应，请稍后...');
      await customAlert.value.open('正在等待上一次请求的响应，请稍后...');
      console.log('按钮已经被点击，正在等待上一次请求的响应...');
      return;
    }
    // 按钮被点击，设置状态为 true
    isButtonClicked.value = true;
    isModalVisible.value = true;
    let response;
    let settings = [];
    let datasets = [];

    switch (buttonId) {
      case 1:
        isInitConfirmationVisible.value = false;
        // 初始化前端页面
        Localuser.value.forEach(user => {
          user.setting = '默认设置';
          user.status = '未训练';
          user.result1 = '未验证';
          user.result2 = '';
        });
        // alert("客户端已开始初始化操作...");

        try {
          response = await apiClient.get('/client_status');
          if (response.status === 200) {
            console.log(response.data)
            const trace_state = response.data.trace_step_status;
            const state = response.data.user.step_status;
            console.log("trace_step_status:", response.data);
            if (state === "step_none") {
              // alert("已全局重置，请重新参与学习");
              await customAlert.value.open("已全局重置，请重新参与学习");
              // showAlert("已全局重置，请重新参与学习");
              // 设置按钮状态
              set_buttons(response.data.user.step_status);
            } else if (trace_state === "step_none") {
              // alert("追踪服务器尚未完成初始化，请稍后重试");
              await customAlert.value.open("追踪服务器尚未完成初始化，请稍后重试");
              // showAlert("追踪服务器尚未完成初始化，请稍后重试");
            } else {
              response = await apiClient.post(`/init`);
              console.log('初始化成功', response.data);
              // 更新数据集选项
              settingData.value = response.data.datasets;
              Localuser.value.forEach(user => {
                user.dataset = response.data.datasets[0];
                user.client_id = response.data.client_id;
              });
              // alert("客户端初始化完成")
              // showAlert("客户端初始化完成")
              await customAlert.value.open("客户端初始化完成");
              saveUsersToSessionStorage();
              update_client_status();
            }
          }
        } catch (error) {
          console.error('初始化失败', error);
        }

        break;
      case 2:
        response = await apiClient.get('/client_status');
        if (response.status === 200) {
          console.log(response.data)
          const trace_state = response.data.trace_step_status;
          console.log("trace_step_status:", response.data);
          if (trace_state === "step_none") {
            // alert("已全局重置，请重新参与学习");
            // showAlert("已全局重置，请重新参与学习");
            await customAlert.value.open("已全局重置，请重新参与学习");
            console.log(response.data);
            console.log(response.data.user.name);
            console.log(userInfo_userId.value);
            // 从后端获取并更新 Localuser 信息
            Localuser.value.forEach(user => {
              user.name = response.data.user.name;
              user.setting = response.data.user.setting;
              user.dataset = response.data.user.dataset;
              user.status = response.data.user.status;
              user.result1 = response.data.user.result1;
              user.result2 = response.data.user.result2;
              user.client_id = response.data.user.client_id;
            });
            // 设置按钮状态
            set_buttons(response.data.user.step_status);
            if (response.data.user.step_status !== "step_none") {
              // 判断 user.name 与 userInfo.userid 是否相等
              isLocked.value = (response.data.user.name !== userInfo_username.value);
            }
            if (response.data.user.step_status === "step_none") {
              settingData.value = [...initialDataset];
            }
          } else {
            // showAlert("客户端模型已开始训练，请耐心等待...");

            await customAlert.value.open("客户端模型已开始训练，请耐心等待...");
            try {
              // 统计所有用户的setting值，并向后端发送请求
              settings = Localuser.value.map(user => convertSettingToNumber(user.setting));
              datasets = Localuser.value.map(user => (user.dataset));
              set_buttons("step_train_start")
              response = await apiClient.post('/local_train', {local_setting: settings[0], local_dataset: datasets[0]});
              Localuser.value.forEach(user => {
                user.status = '训练完成';
              });
              console.log('训练完成', response.data);
              update_client_status();
              // saveUsersToSessionStorage();
              // alert("客户端训练完成")
            } catch (error) {
              console.error('训练失败', error);
              // train_condition.value = true;
            }
            console.log('开始训练');
          }
        }
        break;
      case 3:
        response = await apiClient.get('/client_status');
        if (response.status === 200) {
          console.log(response.data)
          const trace_state = response.data.trace_step_status;
          console.log("trace_step_status:", response.data);
          const agg_state = response.data.agg_step_status;
          console.log("agg_step_status:", response.data);
          if (trace_state === "step_none") {
            // showAlert("已全局重置，请重新参与学习");
            await customAlert.value.open("已全局重置，请重新参与学习");
            console.log(response.data);
            console.log(response.data.user.name);
            console.log(userInfo_userId.value);
            // 从后端获取并更新 Localuser 信息
            Localuser.value.forEach(user => {
              user.name = response.data.user.name;
              user.setting = response.data.user.setting;
              user.dataset = response.data.user.dataset;
              user.status = response.data.user.status;
              user.result1 = response.data.user.result1;
              user.result2 = response.data.user.result2;
              user.client_id = response.data.user.client_id;
            });
            // 设置按钮状态
            set_buttons(response.data.user.step_status);
            if (response.data.user.step_status !== "step_none") {
              // 判断 user.name 与 userInfo.userid 是否相等
              isLocked.value = (response.data.user.name !== userInfo_username.value);
            }
            if (response.data.user.step_status === "step_none") {
              settingData.value = [...initialDataset];
            }
          } else if (agg_state === "step_none") {
            // showAlert("聚合服务器尚未完成初始化，请稍后重试");
            await customAlert.value.open("聚合服务器尚未完成初始化，请稍后重试");
          } else {
            response = await apiClient.post('/upload', {local_settings: settings, local_datasets: datasets});
            console.log('上传模型');
            Localuser.value.forEach(user => {
              user.status = '已上传';
            });

            saveUsersToSessionStorage();
            update_client_status();
          }
        }
        break;
      case 4:
        console.log('接收模型');
        // 逻辑代码
        break;
      case 5:
        response = await apiClient.get('/client_status');
        if (response.status === 200) {
          console.log(response.data)
          const trace_state = response.data.trace_step_status;
          console.log("trace_step_status:", response.data);
          if (trace_state === "step_none") {
            // showAlert("已全局重置，请重新参与学习");
            await customAlert.value.open("已全局重置，请重新参与学习");
            console.log(response.data);
            console.log(response.data.user.name);
            console.log(userInfo_userId.value);
            // 从后端获取并更新 Localuser 信息
            Localuser.value.forEach(user => {
              user.name = response.data.user.name;
              user.setting = response.data.user.setting;
              user.dataset = response.data.user.dataset;
              user.status = response.data.user.status;
              user.result1 = response.data.user.result1;
              user.result2 = response.data.user.result2;
              user.client_id = response.data.user.client_id;
            });
            // 设置按钮状态
            set_buttons(response.data.user.step_status);
            if (response.data.user.step_status !== "step_none") {
              // 判断 user.name 与 userInfo.userid 是否相等
              isLocked.value = (response.data.user.name !== userInfo_username.value);
            }
            if (response.data.user.step_status === "step_none") {
              settingData.value = [...initialDataset];
            }
          } else {
            // showAlert("客户端开始验证聚合模型...");
            await customAlert.value.open("客户端开始验证聚合模型...");
            try {
              response = await apiClient.post('/verify');
              console.log('验证完成', response.data);
              if (response.data.verify_result) {
                Localuser.value.forEach(user => {
                  user.result1 = '验证成功';
                });
              } else {
                Localuser.value.forEach(user => {
                  user.result1 = '验证失败';
                });
              }
              // showAlert("客户端验证完成");
              await customAlert.value.open("客户端验证完成");
            } catch (error) {
              console.error('验证', error);
            }
            console.log('验证模型');
            // 逻辑代码
            saveUsersToSessionStorage();
            update_client_status();
          }
        }

        break;
      case 6:
        update_client_status();
        // alert("尝试参与联邦学习...");
        // showAlert("尝试参与联邦学习...")

        await customAlert.value.open('尝试参与联邦学习...');
        try {
          let user = {
            client_id: userInfo_clientId.value,
            userid: userInfo_userId.value,
            username: userInfo_username.value,
          };
          response = await apiClient.post('/login', {
            'user': user
          });
          if (response.status === 200) {
            if (response.data.status === "wait") {
              // showAlert("学习已经开始，请等待新一轮学习")
              await customAlert.value.open("学习已经开始，请等待新一轮学习");
            } else {
              console.log('尝试参与学习', response.data);
              console.log('response.data.firstLogin', response.data.firstLogin);
              console.log('userInfo_userId.value', userInfo_userId.value)
              console.log('String(response.data.firstLogin) !== String(userInfo_userId.value)', String(response.data.firstLogin) !== String(userInfo_userId.value))
              if (response.data.firstLogin && String(response.data.firstLogin) !== String(userInfo_userId.value)) {
                // showAlert("已有用户" + response.data.firstLogin + "正在使用");
                await customAlert.value.open("已有用户" + response.data.firstLogin + "正在使用");
              }
            }
            update_manage_datasets();
            update_client_status();
          }
        } catch (error) {
          console.error('尝试参与学习', error);
        }
        console.log('参与学习');
        // 逻辑代码
        saveUsersToSessionStorage();
        update_client_status();
        break;
      default:
        break;
    }
  } catch (error) {
    console.error('Error handling button click:', error);
  } finally {
    // 在请求完成后，重置按钮点击状态
    // if(!train_condition.value){
    //   train_condition.value = false;
    //   isButtonClicked.value = false;
    //   isModalVisible.value = false;
    // }
    isButtonClicked.value = false;
    isModalVisible.value = false;
  }
};

const downloadFile = async () => {
  try {
    // const response = await axios.get(`${process.env.VUE_APP_BACKEND_API}/Getmodel`, {
    const response = await apiClient.get(`/Getmodel`, {
      responseType: 'blob', // Important to receive the file as a Blob
    });

    const url = window.URL.createObjectURL(new Blob([response.data]));
    const link = document.createElement('a');
    link.href = url;
    link.setAttribute('download', 'model.pth'); // or any other extension
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  } catch (error) {
    console.error('Error downloading file:', error);
  }
};
const downloadFile1 = async () => {
  try {
    // const response1 = await axios.get(`${process.env.VUE_APP_BACKEND_API}/Getfiles`, {
    const response1 = await apiClient.get(`/Getfiles`, {
      responseType: 'blob',
      params: {
        file: "guide"
      }
    });
    const response2 = await apiClient.get(`/Getfiles`, {
      responseType: 'blob',
      params: {
        file: "demo"
      }
    });
    const url1 = window.URL.createObjectURL(new Blob([response1.data]));
    const url2 = window.URL.createObjectURL(new Blob([response2.data]));
    const link1 = document.createElement('a');
    link1.href = url1;
    link1.setAttribute('download', 'model.pth的使用说明.docx'); // 设置第一个文件的下载属性
    document.body.appendChild(link1);
    link1.click();
    document.body.removeChild(link1);
    const link2 = document.createElement('a');
    link2.href = url2;
    link2.setAttribute('download', 'demo.py'); // 设置第二个文件的下载属性
    document.body.appendChild(link2);
    link2.click();
    document.body.removeChild(link2);
  } catch (error) {
    console.error('Error downloading files:', error);
  }
};

// 注销客户端
// const logoutUser = async () => {
//   try {
//     const response = await apiClient.delete('/delete_client', {
//       data: { client_id: Localuser.value[0].client_id }
//     });
//
//     if (response.status === 200) {
//       alert('注销成功');
//       Localuser.value = [];
//       saveUsersToSessionStorage();
//     } else {
//       alert('注销失败，请稍后重试');
//     }
//   } catch (error) {
//     console.error('注销请求失败:', error);
//     alert('注销请求失败，请稍后重试');
//   }
// };


// //用于注销客户端
// const isLogoutConfirmationVisible = ref(false);
// const showLogoutConfirmation = () => {
//   isLogoutConfirmationVisible.value = true;
// };
// const cancelLogout = () => {
//   isLogoutConfirmationVisible.value = false;
// };
// // 确认注销
// const logout = async () => {
//   try {
//     const response = await apiClient.post('/logout');
//
//     if (response.status === 200) {
//       console.log('注销成功，服务器数据已删除');
//       // 执行注销逻辑，例如清除 sessionStorage、重定向等
//       alert("客户端注销成功")
//       sessionStorage.clear();
//       window.location.reload(); // 重新加载页面
//     } else {
//       alert("客户端注销失败，请重试")
//       console.error('注销失败:', response.data);
//     }
//   } catch (error) {
//     alert("客户端注销请求失败，请重试")
//     console.error('注销请求失败:', error);
//   }
// };

// 按钮状态赋值
const set_buttons = async (step_status) => {
  if (step_status === "step_none") {
    buttons_status.value = [false, true, true, true, true, true, true, false];
  } else if (step_status === "step_login_done") {
    buttons_status.value = [true, false, true, true, true, true, true, false];
  } else if (step_status === "step_init_done") {
    buttons_status.value = [true, true, false, true, true, true, true, false];
  } else if (step_status === "step_train_done") {
    buttons_status.value = [true, true, true, false, true, true, true, false];
  } else if (step_status === "step_upload_done") {
    buttons_status.value = [true, true, true, true, true, true, true, false];
  } else if (step_status === "step_update_done") {
    buttons_status.value = [true, true, true, true, false, true, true, false];
  } else if (step_status === "step_verify_true") {
    buttons_status.value = [true, true, false, true, true, true, false, false];
  } else if (step_status === "step_verify_false") {
    buttons_status.value = [true, true, true, true, true, false, true, false];
  } else if (step_status === "step_trace_done") {
    buttons_status.value = [true, true, false, true, true, true, false, false];
  } else if (step_status === "step_train_start") {
    buttons_status.value = [true, true, false, true, true, true, true, true];
  }
  console.log("buttons_status:", buttons_status.value)
};

// 页面锁定
const isLocked = ref(false); // 控制锁定状态
// isLocked.value = (2 !== 1);


// 页面刷新
// 向后端获取前端状态
const update_client_status = async () => {
  loadUsersFromSessionStorage();
  try {
    // 发送 Localuser 数据给后端
    const response = await apiClient.get('/client_status');
    if (response.status === 200) {
      console.log(response.data);
      console.log(response.data.user.name);
      console.log(userInfo_userId.value);
      // 从后端获取并更新 Localuser 信息
      Localuser.value.forEach(user => {
        user.name = response.data.user.name;
        user.setting = response.data.user.setting;
        user.dataset = response.data.user.dataset;
        user.status = response.data.user.status;
        user.result1 = response.data.user.result1;
        user.result2 = response.data.user.result2;
        user.client_id = response.data.user.client_id;
      });
      settingData.value = response.data.user.datasets;
      if(response.data.user.manage_datasets){
        manage_datasets.value = response.data.user.manage_datasets;
      }
      // 设置按钮状态
      set_buttons(response.data.user.step_status);
      if (response.data.user.step_status !== "step_none") {
        // 检查 user.name 是否为空
        console.log(response.data.user.name)
        if (response.data.user.name) {
          // 判断 user.name 与 userInfo.userid 是否相等
          isLocked.value = (response.data.user.name !== userInfo_username.value);
          console.log("set buttons locked")
        } else {
          // 如果 user.name 为空，设置 isLocked 为 false
          isLocked.value = false;
        }
      }
      // if (response.data.user.step_status === "step_none") {
      //   settingData.value = [...initialDataset];
      //   isLocked.value = false;
      // }
      if (!response.data.user.agg_verify) {
        // showAlert("聚合服务器验证失败，请重新训练")
        await customAlert.value.open("聚合服务器验证失败，请重新训练");
      }
      sessionStorage.setItem('local_user', JSON.stringify(Localuser.value));// 保存到 sessionStorage
      sessionStorage.setItem('local_dataset', JSON.stringify(settingData.value));
    }
  } catch (error) {
    console.error('更新用户信息失败:', error);
  }
  saveUsersToSessionStorage();
  loadUsersFromSessionStorage();
};

const update_manage_datasets = async () => {
  loadUsersFromSessionStorage();
  try {
    // 发送 Localuser 数据给后端
    const response = await apiClient.post('/update_manage_datasets');
    if (response.status === 200) {
      console.log(response.data);
      console.log(response.data.manage_datasets);
      manage_datasets.value = response.data.manage_datasets;
    }
  } catch (error) {
    console.error('更新用户信息失败:', error);
  }
  saveUsersToSessionStorage();
  loadUsersFromSessionStorage();
};

// 数据集管理相关操作
const isDeleteConfirmationVisible = ref(false); // 弹窗显示状态
const selectedDataset = ref(null); // 当前选中的数据集

// 显示弹窗
const showDeleteConfirmation = async (dataset) => {
  let response;
  response = await apiClient.get('/client_status');
  if (response.status === 200) {
    const trace_state = response.data.trace_step_status;
    if (trace_state === "step_train_start") {
      await customAlert.value.open("训练已开始，请稍后重试");
    }
  }
  selectedDataset.value = dataset;
  isDeleteConfirmationVisible.value = true;
};

// // 确认删除操作
// const confirmDelete = () => {
//   if (selectedDataset.value) {
//     const datasetIndex = manage_datasets.value.findIndex(
//         (item) => item.dataset_name === selectedDataset.value.dataset_name
//     );
//     if (datasetIndex > -1) {
//       manage_datasets.value.splice(datasetIndex, 1); // 删除数据集
//       alert(`数据集 "${selectedDataset.value.dataset_name}" 已成功删除！`);
//     }
//   }
//   saveUsersToSessionStorage();
//   closeDeleteModal();
// };

// 确认删除
const confirmDelete = async () => {
  try {
    await update_client_status();
    await update_manage_datasets();
    // set_buttons("step_train_start")
    if(buttons_status.value[7]===false){
      const response = await apiClient.post('/delete_dataset', {dataset_name: selectedDataset.value.dataset_name})
      if (response.data.success) {
        // 更新前端状态，例如重新获取数据集
        update_client_status();
        await customAlert.value.open("数据集已删除");
      } else {
        // alert('删除失败: ' + response.data.error)
        await customAlert.value.open('删除失败: ' + response.data.error);
     }
    }else{
      await customAlert.value.open('正在训练，请稍后重试');
    }
    update_manage_datasets();
  } catch (error) {
    console.error('删除数据集失败:', error)
    // alert('删除操作失败，请稍后再试')
    await customAlert.value.open(error,' 请稍后再试');
  } finally {
    isDeleteConfirmationVisible.value = false
  }
}

// 取消删除操作
const cancelDelete = () => {
  closeDeleteModal();
};

// 关闭弹窗
const closeDeleteModal = () => {
  isDeleteConfirmationVisible.value = false;
  selectedDataset.value = null;
};

const isCreateDatasetVisible = ref(false); // 新建数据集弹窗显示状态
const selectedFile = ref(null); // 选择的文件
const uploading = ref(false); // 上传状态
const fileInput = ref(null); // 用于获取文件输入框的引用
const MAX_FILE_SIZE = 10 * 1024 * 1024; // 最大文件大小 10MB
// 显示新建数据集弹窗
const showCreateDatasetModal = () => {
  isCreateDatasetVisible.value = true;
};

// 选择文件后触发
const handleFileChange = async (event) => {
  const file = event.target.files[0];

  // 检查文件格式
  if (file && file.name.endsWith(".npz")) {
    // 检查文件大小
    if (file.size > MAX_FILE_SIZE) {
      await customAlert.value.open('文件大小超过限制（10MB）。');
      selectedFile.value = null;
      // 清除文件输入框的值
      fileInput.value.value = "";
      return;
    }

    selectedFile.value = file;
  } else {
    // alert("请上传 .npz 格式的文件！");
    await customAlert.value.open('请上传 .npz 格式的文件！');
    selectedFile.value = null;
    // 清除文件输入框的值
    fileInput.value.value = "";
  }
};

// 上传文件
const uploadFile = async (file) => {
  const formData = new FormData();
  // 修改为 files[] 来适配后端接口
  formData.append("files[]", file);
  try {
    const response = await apiClient.post("/upload_dataset", formData, {
      headers: {
        "Content-Type": "multipart/form-data",
      },
    });
    if (response.status === 200) {
      update_manage_datasets();
      await customAlert.value.open('数据集上传成功！');

    } else {
      await customAlert.value.open('数据集上传失败：' + response.data.error);
    }
  } catch (error) {
    // 判断是否为 Axios 响应错误
    if (error.response) {
      // 使用后端返回的错误信息
      await customAlert.value.open('数据集上传失败：' + error.response.data.error);
    } else {
      // 处理其他错误
      await customAlert.value.open('上传失败，发生未知错误');
    }
    console.error(error);
  }
};

// 确认新建数据集
const confirmCreate = async () => {
  if (selectedFile.value) {
    uploading.value = true; // 开始上传
    await uploadFile(selectedFile.value); // 上传文件
    uploading.value = false; // 上传完成
  }
  update_client_status();
  closeCreateModal();
};

// 取消操作
const cancelCreate = () => {
  closeCreateModal();
};

// 关闭弹窗
const closeCreateModal = () => {
  isCreateDatasetVisible.value = false;
  selectedFile.value = null;
  // 清除文件输入框的值
  fileInput.value.value = "";
};

// // 模拟数据集
// const manage_datasets = ref(
//     Array.from({length: 120}, (_, i) => ({
//       dataset_name: `数据集 ${i + 1}`,
//       upload_time: `2024-11-${Math.floor(i / 3) + 1} ${10 + (i % 3)}:00`,
//     }))
// );

// 当前页码和分页相关
const currentPage = ref(1); // 当前页码
const itemsPerPage = 10; // 每页显示的数据条数
const inputPage = ref(""); // 输入的页码

// 分页数据
const paginatedData = computed(() =>
    manage_datasets.value.slice(
        (currentPage.value - 1) * itemsPerPage,
        currentPage.value * itemsPerPage
    )
);

// 总页数
const totalPages = computed(() =>
    Math.ceil(manage_datasets.value.length / itemsPerPage)
);

// 动态显示的页码
const visiblePages = computed(() => {
  const maxVisiblePages = 7; // 最多显示页码数
  const pages = [];

  if (totalPages.value <= maxVisiblePages) {
    // 页数少于或等于最大可见页码数，全部显示
    for (let i = 1; i <= totalPages.value; i++) {
      pages.push(i);
    }
  } else {
    // 页数多于最大可见页码数，显示省略号
    if (currentPage.value <= 4) {
      // 当前页接近开头
      pages.push(1, 2, 3, 4, 5, "...", totalPages.value);
    } else if (currentPage.value > totalPages.value - 4) {
      // 当前页接近结尾
      pages.push(
          1,
          "...",
          totalPages.value - 4,
          totalPages.value - 3,
          totalPages.value - 2,
          totalPages.value - 1,
          totalPages.value
      );
    } else {
      // 当前页在中间
      pages.push(
          1,
          "...",
          currentPage.value - 1,
          currentPage.value,
          currentPage.value + 1,
          "...",
          totalPages.value
      );
    }
  }

  return pages;
});

// 跳转到上一页
const prevPage = () => {
  if (currentPage.value > 1) currentPage.value--;
};

// 跳转到下一页
const nextPage = () => {
  if (currentPage.value < totalPages.value) currentPage.value++;
};

// 跳转到指定页码
const jumpToPage = async (page) => {
  if (page === "...") return;
  if (page >= 1 && page <= totalPages.value) {
    currentPage.value = page;
  } else {
    // alert(`无效的页码，请输入1到${totalPages.value}之间的数字`);
    await customAlert.value.open(`无效的页码，请输入1到${totalPages.value}之间的数字`);
  }
};

// 输入跳转页码
const goToPage = async () => {
  const targetPage = parseInt(inputPage.value);
  if (isNaN(targetPage) || targetPage < 1 || targetPage > totalPages.value) {
    // alert(`无效的页码，请输入1到${totalPages.value}之间的数字`);
    await customAlert.value.open(`无效的页码，请输入1到${totalPages.value}之间的数字`);
  } else {
    currentPage.value = targetPage;
  }
  inputPage.value = ""; // 清空输入框
};


// 封装函数
const getUserInfo = () => {
  const userTag = document.querySelector('user');
  if (userTag) {
    return {
      clientId: userTag.getAttribute('client_id'),
      userId: userTag.getAttribute('userid'),
      username: userTag.getAttribute('username'),
    };
  }
  return null; // 如果没有找到标签，返回 null
};

const formatResult = (result) => {
  return result.split(',').map(item => item.trim()).join('<br>');
};

const store = useStore();
const hideSidebar = () => store.commit('hideSidebar');
const showSidebar = () => store.commit('showSidebar');

onMounted(() => {
  hideSidebar();
  loadUsersFromSessionStorage();
  // checkLockStatus();// 组件挂载时检查锁定状态
  const userInfo = getUserInfo();
  if (userInfo) {
    userInfo_clientId.value = userInfo.clientId;
    userInfo_userId.value = userInfo.userId;
    userInfo_username.value = userInfo.username;
    console.log('Client ID:', userInfo.clientId);
    console.log('User ID:', userInfo.userId);
    console.log('Username:', userInfo.username);
  }
  update_manage_datasets();
  update_client_status();

  // connectWebSocket();
});

onUnmounted(() => {
  showSidebar();
  saveUsersToSessionStorage();
  // if (socket) {
  //   socket.disconnect();
  // }
});
</script>


<style scoped nonce="randomNonceValue">
.container {
  margin-top: 20px;
}

.card {
  margin-top: 10px;
}

.table-responsive {
  max-height: 400px;
  overflow-y: auto;
}

table {
  width: 100%;
  margin-bottom: 1rem;
  color: #212529;
  border-collapse: separate;
  border-spacing: 1px 2px;
}

.btn-secondary {
  background-color: #6c757d;
}

.btn-secondary.disabled {
  background-color: #e9ecef;
  cursor: not-allowed;
}

.bg-primary-light {
  background-color: #5e72e4 !important; /* 淡蓝色 */
}

.bg-secondary-light {
  background-color: #aba8a8 !important; /* 淡灰色 */
}

.btn-secondary.disabled {
  pointer-events: none;
  opacity: 1;
}

.disabled1 {
  pointer-events: none;
  opacity: 1;
}

.bg-primary-heavy {
  background-color: #152ca8 !important; /* 淡蓝色 */
}

.bg-danger-light {
  background-color: #c03427 !important; /* 淡灰色 */
}

.btn-secondary.disabled {
  pointer-events: none;
  opacity: 1;
}

.disabled1 {
  pointer-events: none;
  opacity: 1;
}

.modal {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
}

.modal-content {
  background: white;
  padding: 20px;
  border-radius: 5px;
  text-align: center;
}

/*窗口动效*/
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(255, 255, 255, 0.7);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.modal-content {
  width: 30%; /* 宽度 */
  aspect-ratio: 16/6;
  background-color: #c9dafc;
  padding: 20px;
  border-radius: 8px;
  text-align: center;
}

.spinner {
  border: 4px solid rgba(255, 255, 255, 0.2);
  border-left-color: #152ca8;
  border-radius: 50%;
  width: 40px;
  height: 40px;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

/*初始化弹窗*/
.modal {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
}

.modal-content {
  background: white;
  padding: 20px;
  border-radius: 5px;
  text-align: center;
}

/*禁用页面*/
.locked {
  pointer-events: none; /* 禁用所有指针事件 */
  opacity: 0.5; /* 更改透明度以显示锁定状态 */
}

.page-btn {
  background-color: #ffffff; /* 按钮背景色 */
  color: #07102b; /* 按钮文字颜色 */
  //border: none;             /* 无边框 */
  //border-radius: 5px;       /* 边角圆润 */
  width: 100px; /* 按钮宽度 */
  height: 40px; /* 按钮高度 */
  //margin-left: 10px;        /* 按钮间距 */
  font-size: 16px; /* 字体大小 */
  cursor: pointer; /* 鼠标样式 */
  transition: background-color 0.3s ease;
  display: flex; /* 居中对齐 */
  justify-content: center;
  align-items: center;
}

.page-btn.active {
  background-color: #eeeaea; /* 悬停时颜色 */
  color: #152ca8; /* 按钮文字颜色 */
}

.page-btn:hover {
  background-color: rgb(217, 217, 217); /* 悬停时颜色 */
  color: #425be0; /* 按钮文字颜色 */
}

/* 顶部按钮样式 */
.btn-add {
  background-color: #152ca8;
  color: white;
  border: none;
  border-radius: 5px;
  padding: 10px 20px;
  cursor: pointer;
  font-size: 14px;
  transition: background-color 0.3s ease;
}

.btn-add:hover {
  background-color: #425be0;
}

/* 表格样式 */
.data-table {
  width: 100%;
  border-collapse: collapse;
  text-align: left;
  font-size: 14px;
}

.data-table th,
.data-table td {
  border: 1px solid #ddd;
  padding: 8px;
}

.data-table th {
  background-color: #f4f4f4;
  font-weight: bold;
}

.row-odd {
  background-color: #f9f9f9;
}

.row-even {
  background-color: #ffffff;
}

.data-table tr:hover {
  background-color: #f1f1f1;
}

/* 删除按钮样式 */
.btn-action {
  background-color: #152ca8;
  color: white;
  border: none;
  border-radius: 5px;
  padding: 5px 10px;
  cursor: pointer;
  font-size: 12px;
  transition: background-color 0.3s ease;
}

.btn-action:hover {
  background-color: #425be0;
}

.btn-action:disabled {
  cursor: not-allowed;
  background-color: #c0c0c0; /* 禁用状态背景颜色 */
}

/* 分页样式 */
.pagination-container {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 20px;
}

.pagination-info {
  font-size: 14px;
}

.pagination {
  display: flex;
  align-items: center;
  gap: 5px;
}

.pagination button {
  padding: 5px 10px;
  font-size: 12px;
  border: none;
  border-radius: 5px;
  cursor: pointer;
}

.pagination button:disabled {
  background-color: #e9ecef;
  cursor: not-allowed;
}

.pagination span {
  padding: 5px 10px;
  border-radius: 5px;
  cursor: pointer;
}

.pagination span.active {
  background-color: #152ca8;
  color: white;
}

.jump-to {
  display: flex;
  align-items: center;
  font-size: 14px;
}

.jump-to input {
  width: 50px;
  margin-left: 5px;
  padding: 2px 5px;
  font-size: 14px;
  border: 1px solid #ccc;
  border-radius: 5px;
  text-align: center;
}

/* 删除数据集弹窗 */
.delete-modal {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
}

.delete-modal-content {
  background-color: white;
  padding: 20px;
  border-radius: 8px;
  text-align: center;
  width: 450px; /* 弹窗宽度 */
  height: 270px; /* 弹窗高度 */
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
  display: flex;
  flex-direction: column;
  justify-content: space-between; /* 让标题和按钮分别靠近顶部和底部 */
}

.delete-modal-title {
  font-size: 18px;
  color: #333;
  margin-top: 0; /* 去除顶部间距，让标题紧贴顶部 */
  margin-bottom: 20px; /* 增加与内容的间距 */
  text-align: left;
}

.delete-modal-message {
  font-size: 16px;
  margin-bottom: 30px; /* 保持与按钮的间距 */
  color: #333;
}

.delete-modal-buttons {
  display: flex;
  justify-content: flex-end;
  gap: 20px; /* 增加按钮之间的间距 */
}

.btn {
  padding: 10px 20px;
  font-size: 14px;
  border: none;
  border-radius: 5px;
  cursor: pointer;
}

.delete-confirm-btn {
  background-color: #152ca8; /* 深蓝色 */
  color: white;
}

.delete-confirm-btn:hover {
  background-color: #425be0; /* 深蓝色 hover */
  color: white;
}

.delete-cancel-btn {
  background-color: white;
  color: black;
  border: 1px solid #ddd;
}

.delete-cancel-btn:hover {
  background-color: #f5f5f5;
}

/*新增数据集弹窗*/
.create-modal {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
}

.create-modal-content {
  background-color: white;
  padding: 20px;
  border-radius: 8px;
  text-align: center;
  width: 500px; /* 弹窗宽度 */
  height: 300px; /* 弹窗高度 */
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

.create-modal-title {
  font-size: 18px;
  color: #333;
  margin-top: 0;
  margin-bottom: 20px;
  text-align: left;
}

.upload-row {
  display: flex;
  align-items: center;
  margin-bottom: 0px;
  white-space: nowrap; /* 防止换行 */
  gap: 10px; /* 增加子元素之间的间距 */
  width: 100%; /* 保证行内容占满父容器 */
}

.add-row {
  padding-left: 20px; /* 控制文字右移距离 */
  display: flex;
  flex-direction: column; /* 子元素垂直排列 */
  gap: 0px; /* 设置两行之间的间距 */
}

.upload-label {
  font-size: 16px;
  color: #333;
  white-space: nowrap; /* 确保标签不换行 */
}

.file-input {
  padding: 10px;
  font-size: 14px;
  width: 100%; /* 使文件选择框宽度自适应父容器 */
  min-width: 150px; /* 防止文件框过小 */
  max-width: 250px; /* 限制文件框最大宽度 */
}

.file-info {
  font-size: 12px;
  color: #666;
  padding-left: 5px; /* 控制文字右移距离 */
  text-align: right;
}

.create-modal-buttons {
  display: flex;
  justify-content: flex-end;
  gap: 20px;
}

.btn {
  padding: 10px 20px;
  font-size: 14px;
  border: none;
  border-radius: 5px;
  cursor: pointer;
}

.create-confirm-btn {
  background-color: #152ca8; /* 深蓝色 */
  color: white;
}

.create-confirm-btn:disabled {
  background-color: #ccc; /* 禁用状态 */
  cursor: not-allowed;
}

.create-confirm-btn:hover {
  background-color: #1e40af; /* 深蓝色 hover */
  color: white;
}

.create-cancel-btn {
  background-color: white;
  color: black;
  border: 1px solid #ddd;
}

.create-cancel-btn:hover {
  background-color: #f5f5f5;
}

</style>
